package br.usp.ime.ingpos.web.controllers;

import java.util.ArrayList;
import java.util.List;

import org.springframework.util.StringUtils;

import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.validator.Validations;
import br.com.caelum.vraptor.view.Results;
import br.usp.ime.ingpos.modelo.AreaDePesquisa;
import br.usp.ime.ingpos.modelo.Inscricao;
import br.usp.ime.ingpos.modelo.Orientador;
import br.usp.ime.ingpos.modelo.ProcessoSeletivo;
import br.usp.ime.ingpos.modelo.TipoPerfil;
import br.usp.ime.ingpos.modelo.TipoProcessoSeletivo;
import br.usp.ime.ingpos.services.AreaDePesquisaService;
import br.usp.ime.ingpos.services.CandidatoService;
import br.usp.ime.ingpos.services.InscricaoService;
import br.usp.ime.ingpos.services.OrientadorService;
import br.usp.ime.ingpos.services.ProcessoSeletivoService;
import br.usp.ime.ingpos.services.UsuarioService;
import br.usp.ime.ingpos.web.interceptors.RestrictAccessPerfil;
import br.usp.ime.ingpos.web.interceptors.Transactional;

@Resource
public class CursoController
{
    private final Result result;
    private final Validator validador;

    private final UsuarioSessao usuarioSessao;
    private final CandidatoService candidatoService;
    private final ProcessoSeletivoService processoSeletivoService;
    private final InscricaoService inscricaoService;
    private final AreaDePesquisaService areaDePesquisaService;
    private final OrientadorService orientadorService;
    private Inscricao inscricao;

    public CursoController(
        final Result result,
        final Validator validator,
        final UsuarioSessao usuarioSessao,
        final CandidatoService candidatoService,
        final ProcessoSeletivoService processoSeletivoService,
        final InscricaoService inscricaoService,
        final AreaDePesquisaService areaDePesquisaService,
        final OrientadorService orientadorService )
    {
        this.result = result;
        this.validador = validator;
        this.usuarioSessao = usuarioSessao;
        this.candidatoService = candidatoService;
        this.processoSeletivoService = processoSeletivoService;
        this.inscricaoService = inscricaoService;
        this.areaDePesquisaService = areaDePesquisaService;
        this.orientadorService = orientadorService;
    }

    public List<String> selecionarAreas(
        Inscricao inscricao )
    {
        List<String> selecionadas = new ArrayList<String>();

        List<AreaDePesquisa> lista = inscricao.getAreasDeInteresseAfinidade1();
        if( lista != null ) {
            for( AreaDePesquisa area : lista ) {
                if( area.isInseridaPelaSecretaria() )
                    selecionadas.add( area.getDescricao() + "1" );
                else
                    selecionadas.add( "outra2" );
            }
        }

        lista = inscricao.getAreasDeInteresseAfinidade2();
        if( lista != null ) {
            for( AreaDePesquisa area : lista ) {
                if( area.isInseridaPelaSecretaria() )
                    selecionadas.add( area.getDescricao() + "2" );
                else
                    selecionadas.add( "outra2" );
            }
        }

        lista = inscricao.getAreasDeInteresseAfinidade3();
        if( lista != null ) {
            for( AreaDePesquisa area : lista ) {
                if( area.isInseridaPelaSecretaria() )
                    selecionadas.add( area.getDescricao() + "3" );
                else
                    selecionadas.add( "outra3" );
            }
        }

        return selecionadas;
    }

    public String procuraOutraArea(
        Inscricao inscricao )
    {
        List<AreaDePesquisa> lista = inscricao.getAreasDeInteresseAfinidade1();
        if( lista != null ) {
            for( AreaDePesquisa area : lista ) {
                if( ! area.isInseridaPelaSecretaria() )
                    return area.getNome();
            }
        }

        lista = inscricao.getAreasDeInteresseAfinidade2();
        if( lista != null ) {
            for( AreaDePesquisa area : lista ) {
                if( ! area.isInseridaPelaSecretaria() )
                    return area.getNome();
            }
        }

        lista = inscricao.getAreasDeInteresseAfinidade3();
        if( lista != null ) {
            for( AreaDePesquisa area : lista ) {
                if( ! area.isInseridaPelaSecretaria() )
                    return area.getNome();
            }
        }

        return "";
    }

    public void configurarResultCursoPretendido()
    {
        Inscricao inscricao = this.inscricao;

        List<AreaDePesquisa> areasDeInteresse = areaDePesquisaService.procurarAreasDePesquisaAtivas();

        if( inscricao == null )
            inscricao = inscricaoService.getInscricaoAtual();

        String orientadorHash = "nao";
        List<Orientador> orientadores = null;
        TipoProcessoSeletivo tipoPos = null;
        
        orientadores = orientadorService.procurarTodosOrientadores();

        if( inscricao == null ) {
            inscricao = new Inscricao();
        } else {
            if( inscricao.getOrientadorDesejado() != null )
            	orientadorHash = inscricao.getOrientadorDesejado().getHash();

            if( inscricao.getProcessoSeletivo() != null )
                tipoPos = inscricao.getProcessoSeletivo().getTipoProcessoSeletivo();
        }
        
        List<ProcessoSeletivo> processos = processoSeletivoService.buscarProcessosSeletivosVigentes();
        
        result.include( "processos", processos);

        result.include( "inscricao", inscricao );
        result.include( "areasSelecionadas", selecionarAreas( inscricao ) );
        result.include( "outra", procuraOutraArea( inscricao ) );
        result.include( "professores", orientadores );

        result.include( "areasDeInteresse", areasDeInteresse );
        result.include( "tipoPos", tipoPos );
        result.include( "orientador", orientadorHash );
    }

    @Get
    @Path( "/curso/cursoPretendido" )
    @RestrictAccessPerfil( values = {
        TipoPerfil.COORDENADOR, TipoPerfil.PROFESSOR, TipoPerfil.SECRETARIA
    } )
    public void cursoPretendido()
    {
        configurarResultCursoPretendido();
    }

    @Post
    @Path( "/curso/cursoPretendido" )
    @Transactional
    public void cursoPretendido(
        final Inscricao inscricao,
        final TipoProcessoSeletivo tipoPos,
        final String orientadorDesejadoHash,
        final List<Long> listaAreasAfinidade1,
        final List<Long> listaAreasAfinidade2,
        final List<Long> listaAreasAfinidade3,
        final String outraArea,
        final Long processoSeletivoId)
    {
        validador.checking( new Validations() {
            {
            	if( processoSeletivoId == null)
            	{
            		that( false, "erro_tipo_programa", "erro_nenhum_selecionado" );
            	}
            	else
            	{
	                that( StringUtils.hasText( inscricao.getDedicacaoExclusiva() ),
	                    "erro_tipo_dedicacao_exclusiva", "erro_campo_nulo" );
	
	                that( StringUtils.hasText( inscricao.getExposicaoPropositos() ),
	                    "erro_tipo_exposicao_propositos", "erro_campo_nulo" );
	
	                if( inscricao.isSabeAreasDeInteresse() == true && listaAreasAfinidade1 == null
	                    && listaAreasAfinidade2 == null && listaAreasAfinidade3 == null )
	                    that( false, "erro_tipo_areas_afinidade", "erro_nenhuma_selecionada" );
            	}
            }
        } );
        
        validador.onErrorForwardTo( getClass() ).cursoPretendido();

        inscricao.setAreasDeInteresseAfinidade1( criaListaAreasInteresse( listaAreasAfinidade1,
            outraArea ) );
        inscricao.setAreasDeInteresseAfinidade2( criaListaAreasInteresse( listaAreasAfinidade2,
            outraArea ) );
        inscricao.setAreasDeInteresseAfinidade3( criaListaAreasInteresse( listaAreasAfinidade3,
            outraArea ) );

//        ProcessoSeletivo processoSeletivo = processoSeletivoService.buscarProcessoSeletivoVigentePorTipo( tipoPos );
//        if( processoSeletivo == null ) {
//            processoSeletivo = new ProcessoSeletivo();
//            processoSeletivo.setTipoProcessoSeletivo( tipoPos );
//        }

        inscricao.setProcessoSeletivo( processoSeletivoService.getProcessoSeletivo( processoSeletivoId ) );
        inscricao.setCandidato( candidatoService.getCandidatoAtual());

        if( ! orientadorDesejadoHash.equals( "nao") )
            inscricao.setOrientadorDesejado( orientadorService.procurarPorHash( orientadorDesejadoHash ) );

        this.inscricao = inscricao;
        validador.onErrorForwardTo( getClass() ).cursoPretendido();
        this.inscricao = null;

        inscricaoService.inserirOuAtualizarInscricao( inscricao );

        result.include( "messages", "curso_pretendido_cadastro_sucesso" );
        result.use( Results.logic() ).redirectTo( IndexController.class ).index();
    }

    private List<AreaDePesquisa> criaListaAreasInteresse(
        List<Long> lista,
        String outra )
    {
        if( lista == null )
            return new ArrayList<AreaDePesquisa>();

        List<AreaDePesquisa> areasDeInteresse = new ArrayList<AreaDePesquisa>();

        for( int i = 0; i < lista.size(); i++ ) {
            if( lista.get( i ) == null )
                break;

            AreaDePesquisa areaDePesquisa;

            if( lista.get( i ).equals( "outra" ) ) {
                areaDePesquisa = areaDePesquisaService.procuraAreaDePesquisaPorNome( outra );
                if( areaDePesquisa == null ) {
                    areaDePesquisa = new AreaDePesquisa( outra, false );
                    areaDePesquisaService.inserirAreaDePesquisa( areaDePesquisa );
                }
                areasDeInteresse.add( areaDePesquisa );
            } else {
                areaDePesquisa = areaDePesquisaService.getAreaDePesquisa( lista.get( i ) );
                areasDeInteresse.add( areaDePesquisa );
            }
        }

        return areasDeInteresse;
    }
}
